#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "hi_io.h"
#include "iot_pwm.h"
#include "hi_pwm.h"
#include "hi_time.h"

/*========================================
 * 硬件配置 - 蜂鸣器+呼吸灯
 ========================================*/
#define BEEP_PWM_PORT        HI_PWM_PORT_PWM2
#define BEEP_GPIO_PIN        HI_IO_NAME_GPIO_11

#define LIGHT_PWM_PORT       HI_PWM_PORT_PWM1
#define LIGHT_GPIO_PIN       HI_IO_NAME_GPIO_10

#define NOTE_DURATION_BASE   1500000  // 慢速播放
#define NOTE_INTERVAL        22000    // 音符间隔

#define BREATH_FREQ          2000     // 呼吸灯频率
#define BREATH_STEP          20       // 呼吸步长
#define BREATH_DELAY         10000    // 呼吸延迟

/*========================================
 * 《小星星》音符频率表
 ========================================*/
static const uint16_t g_tuneFreqs[] = {
    0,      // 0 休止符
    38223,  // 1 中音Do
    34052,  // 2 中音Re
    30338,  // 3 中音Mi
    28635,  // 4 中音Fa
    25511,  // 5 中音So
    22728,  // 6 中音La
    19111,  // 8 高音Do
    17026,  // 9 高音Re
};

/*========================================
 * 《小星星》简谱
 ========================================*/
static const uint8_t g_scoreNotes[] = {
    // 第一段：一闪一闪亮晶晶
    1, 1, 5, 5, 6, 6, 5, 0,
    4, 4, 3, 3, 2, 2, 1, 0,
    
    // 第二段：满天都是小星星
    5, 5, 4, 4, 3, 3, 2, 0,
    5, 5, 4, 4, 3, 3, 2, 0,
    
    // 第三段：挂在天空放光明
    1, 1, 5, 5, 6, 6, 5, 0,
    4, 4, 3, 3, 2, 2, 1, 0
};

static const uint8_t g_scoreDurations[] = {
    // 第一段
    4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4,
    
    // 第二段
    4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4,
    
    // 第三段
    4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4
};

/*========================================
 * 硬件初始化
 ========================================*/
static void Hardware_InitAll(void)
{
    hi_gpio_init();
    
    // 蜂鸣器初始化 (GPIO11/PWM2)
    hi_io_set_func(BEEP_GPIO_PIN, HI_IO_FUNC_GPIO_11_PWM2_OUT);
    hi_pwm_init(BEEP_PWM_PORT);
    
    // 呼吸灯初始化 (GPIO10/PWM1)
    hi_io_set_func(LIGHT_GPIO_PIN, HI_IO_FUNC_GPIO_10_PWM1_OUT);
    hi_pwm_init(LIGHT_PWM_PORT);
    
    hi_pwm_set_clock(PWM_CLK_XTAL);
    printf("硬件初始化完成 - 小星星慢速版\n");
}

/*========================================
 * 呼吸灯控制函数（与音乐同步）
 ========================================*/
static void Control_BreathingLight(uint8_t note, uint32_t duration)
{
    static uint16_t current_duty = 0;
    
    if (note > 0) {
        // 播放音符时，灯光随音符高低变化亮度
        uint16_t target_duty = (note * BREATH_FREQ) / 10; // 根据音符高低决定亮度
        
        // 平滑过渡到目标亮度
        while (current_duty != target_duty) {
            if (current_duty < target_duty) {
                current_duty += BREATH_STEP;
                if (current_duty > target_duty) current_duty = target_duty;
            } else {
                current_duty -= BREATH_STEP;
                if (current_duty < target_duty) current_duty = target_duty;
            }
            
            hi_pwm_start(LIGHT_PWM_PORT, current_duty, BREATH_FREQ);
            hi_udelay(BREATH_DELAY);
        }
        
        // 保持亮度直到音符结束
        hi_udelay(duration);
    } else {
        // 休止符时灯光渐暗
        while (current_duty > 0) {
            current_duty -= BREATH_STEP;
            if (current_duty < 0) current_duty = 0;
            
            hi_pwm_start(LIGHT_PWM_PORT, current_duty, BREATH_FREQ);
            hi_udelay(BREATH_DELAY);
        }
        hi_udelay(duration);
    }
}

/*========================================
 * 播放《小星星》（带呼吸灯同步）
 ========================================*/
static void Play_TwinkleStar_WithLight(void)
{
    size_t scoreLength = sizeof(g_scoreNotes) / sizeof(g_scoreNotes[0]);
    
    printf("\n🌟 === 开始播放：《小星星》（带呼吸灯） === 🌟\n");
    printf("💡 灯光效果：音符高低控制亮度，休止符渐暗\n");
    
    for (size_t i = 0; i < scoreLength; i++) {
        uint8_t note = g_scoreNotes[i];
        uint32_t duration = g_scoreDurations[i] * (NOTE_DURATION_BASE / 4);
        
        if (note > 0 && note < sizeof(g_tuneFreqs)/sizeof(g_tuneFreqs[0])) {
            uint16_t freqDivisor = g_tuneFreqs[note];
            
            printf("🎵 播放: %d (频率:%dHz) 时长:%dms\n", 
                   note, 40000000/freqDivisor, duration/1000);
            
            // 启动蜂鸣器
            hi_pwm_start(BEEP_PWM_PORT, freqDivisor / 2, freqDivisor);
            
            // 同步控制呼吸灯
            Control_BreathingLight(note, duration);
            
            hi_pwm_stop(BEEP_PWM_PORT);
        } else {
            printf("⏸️  休止符 时长:%dms\n", duration/1000);
            Control_BreathingLight(0, duration); // 休止符时灯光渐暗
        }
        
        hi_udelay(NOTE_INTERVAL);
    }
    
    printf("✨ === 《小星星》播放完成 === ✨\n");
}

/*========================================
 * 音乐任务
 ========================================*/
static void Music_Task(void *arg)
{
    (void)arg;
    Hardware_InitAll();
    
    // 先测试音高和灯光
    printf("🔊 音高与灯光测试开始...\n");
    uint8_t testNotes[] = {1, 3, 5, 8}; // Do, Mi, So, 高Do
    for(int i = 0; i < 4; i++) {
        uint16_t freq = g_tuneFreqs[testNotes[i]];
        printf("测试音符 %d (灯光亮度:%d/%d)\n", 
               testNotes[i], (testNotes[i]*BREATH_FREQ)/10, BREATH_FREQ);
        
        hi_pwm_start(BEEP_PWM_PORT, freq/2, freq);
        Control_BreathingLight(testNotes[i], 500000); // 测试0.5秒
        hi_pwm_stop(BEEP_PWM_PORT);
        hi_udelay(300000);
    }
    printf("✅ 测试完成\n");
    
    while (1) {
        Play_TwinkleStar_WithLight();
        printf("\n🔄 等待5秒后重新播放...\n");
        hi_udelay(5000000);
    }
}

/*========================================
 * 系统入口
 ========================================*/
static void Music_Entry(void)
{
    osThreadAttr_t attr = {
        .name = "TwinkleStarWithLight",
        .stack_size = 4096,
        .priority = osPriorityNormal
    };
    
    if (osThreadNew(Music_Task, NULL, &attr) == NULL) {
        printf("创建音乐任务失败!\n");
    } else {
        printf("《小星星》音乐系统启动成功（带呼吸灯同步）!\n");
        printf("🎹 特色功能：\n");
        printf("   - 慢速播放（%.1fs/拍）\n", NOTE_DURATION_BASE/1000000.0);
        printf("   - 灯光亮度随音符高低变化\n");
        printf("   - 休止符时灯光渐暗\n");
    }
}

SYS_RUN(Music_Entry);